package by.grsu.epam.web;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import by.grsu.epam.domain.account.Account;
import by.grsu.epam.domain.account.PayCard;
import by.grsu.epam.domain.account.TelephoneNumber;
import by.grsu.epam.service.entitiesservice.AccountService;
import by.grsu.epam.service.entitiesservice.PayCardService;
import by.grsu.epam.service.entitiesservice.SubscriberService;

@Controller
public class AccountController {

	@Autowired
	private AccountService accountService;

	@Autowired
	private SubscriberService subscriberService;

	@Autowired
	private PayCardService payCardService;

	@RequestMapping(value = "/subscriber/createAccount", method = RequestMethod.GET)
	public ModelAndView createAccountForm() {
		ModelAndView mav = new ModelAndView("/subscriber/createAccount");
		mav.addObject("telephoneNumber", new TelephoneNumber());
		mav.addObject("username", getUsername());
		mav.addObject("accounts", accountService.findAll());

		return mav;
	}

	@RequestMapping(value = "/subscriber/createAccount", method = RequestMethod.POST)
	public ModelAndView createAccount(@ModelAttribute(value = "telephoneNumber") TelephoneNumber number, BindingResult result) {

		ModelAndView mav = new ModelAndView();

		if (result.hasErrors()) {
			mav.setViewName("redirect:/subscriber/createAccount");
		} else {
			mav.setViewName("redirect:/subscriber/home");

			Account account = new Account();
			account.setTelephoneNumber(number);
			account.setSubscriber(subscriberService.findByUsername(getUsername()));

			accountService.save(account);
		}

		return mav;
	}

	// open account profile
	@RequestMapping(value = "/subscriber/account", method = RequestMethod.GET)
	public ModelAndView accountProfile(HttpSession session) {
		ModelAndView mav = new ModelAndView("/subscriber/account");
		Long accountId = (Long) session.getAttribute("accountId");

		Account account = accountService.findById(accountId);
		mav.addObject("mainAccount", account);

		return mav;
	}

	// set selected account id into session
	@RequestMapping(value = "/subscriber/accounts/{accountId}", method = RequestMethod.GET)
	public ModelAndView setAccountId(HttpSession session, @PathVariable Long accountId) {
		ModelAndView mav = new ModelAndView("redirect:/subscriber/account");

		session.setAttribute("accountId", accountId);

		return mav;
	}

	@RequestMapping(value = "/subscriber/account/balance", method = RequestMethod.GET)
	public ModelAndView checkBalance(HttpSession session) {
		ModelAndView mav = new ModelAndView("/subscriber/account/balance");

		Long accountId = (Long) session.getAttribute("accountId");
		Account account = accountService.findById(accountId);
		mav.addObject("mainAccount", account);

		PayCard payCard = new PayCard();
		mav.addObject("payCard", payCard);

		return mav;
	}

	@RequestMapping(value = "/subscriber/account/balance", method = RequestMethod.POST)
	public ModelAndView updateBalance(@ModelAttribute(value = "payCard") PayCard payCard, BindingResult result, HttpSession session) {

		ModelAndView mav = new ModelAndView();

		if (result.hasErrors()) {
			mav.setViewName("redirect:/subscriber/account/balance");
		} else {
			mav.setViewName("redirect:/subscriber/account");

			payCard = payCardService.findBySerialNumber(payCard.getSerialNumber());

			Long accountId = (Long) session.getAttribute("accountId");
			Account account = accountService.findById(accountId);
			account.setBalance(account.getBalance() + payCard.getMoney());

			accountService.update(account);
			payCardService.delete(payCard);
		}

		return mav;
	}

	private String getUsername() {
		Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

		String username;
		if (principal instanceof UserDetails) {
			username = ((UserDetails) principal).getUsername();
		} else {
			username = principal.toString();
		}
		return username;
	}
}
